package com.tianxia120.website;

import com.jfinal.kit.PathKit;
import com.jfinal.plugin.activerecord.dialect.Sqlite3Dialect;
import com.jfinal.plugin.activerecord.generator.ColumnMeta;
import com.jfinal.plugin.activerecord.generator.Generator;
import com.jfinal.plugin.activerecord.generator.MetaBuilder;
import com.jfinal.plugin.activerecord.generator.TableMeta;
import com.jfinal.plugin.hikaricp.HikariCpPlugin;

import javax.sql.DataSource;
import java.sql.*;

/**
 * @createTime: 2018/2/11
 * @author: HingLo
 * @description: 工具
 */
public class JfinalDemoGenerator {
    private static HikariCpPlugin createDruidPlugin() {
        return new HikariCpPlugin("jdbc:sqlite:E:\\Maven\\Website\\src\\main\\resources\\website.db", "", "");
    }

    private static DataSource getDataSource() {
        HikariCpPlugin druidPlugin = createDruidPlugin();
        druidPlugin.setDriverClass("org.sqlite.JDBC");
        druidPlugin.start();

        return druidPlugin.getDataSource();
    }

    public static void main(String[] args) {
        // base entity 所使用的包名
        String baseModelPackageName = "com.tianxia120.website.bean";
        // base entity 文件保存路径
        String baseModelOutputDir = PathKit.getWebRootPath() + "/src/main/java/com/tianxia120/website/bean";

        // entity 所使用的包名 (MappingKit 默认使用的包名)
        String modelPackageName = "com.tianxia120.website.bean.model";
        // entity 文件保存路径 (MappingKit 与 DataDictionary 文件默认保存路径)
        String modelOutputDir = PathKit.getWebRootPath() + "/src/main/java/com/tianxia120/website/bean/model";

        // 创建生成器
        Generator generator = new Generator(getDataSource(), baseModelPackageName, baseModelOutputDir, modelPackageName, modelOutputDir);
        // 设置方言
        generator.setDialect(new Sqlite3Dialect());
        // 重写构造器
        generator.setMetaBuilder(new SqliteMetaBuilder(getDataSource()));

        // 设置是否生成链式 setter 方法
        generator.setGenerateChainSetter(true);
        // 设置是否在 Model 中生成 dao 对象
        generator.setGenerateDaoInModel(true);
        // 设置是否生成字典文件
        generator.setGenerateDataDictionary(false);
        // 设置需要被移除的表名前缀用于生成modelName。例如表名 "osc_user"，移除前缀 "osc_"后生成的model名为 "User"而非 OscUser
//        generator.setRemovedTableNamePrefixes("t_");
        // 生成
        generator.generate();
    }

    /***
     *  重写 metaBuilder  因为 sqlite有问题,生成器返回的都是object类型
     */
    static class SqliteMetaBuilder extends MetaBuilder {
        public SqliteMetaBuilder(DataSource dataSource) {
            super(dataSource);
        }


        @Override
        protected void buildColumnMetas(TableMeta tableMeta) throws SQLException {
            String sql = dialect.forTableBuilderDoBuild(tableMeta.name);
            Statement stm = conn.createStatement();
            ResultSet rs = stm.executeQuery(sql);
            ResultSetMetaData rsmd = rs.getMetaData();

            for (int i = 1; i <= rsmd.getColumnCount(); i++) {
                ColumnMeta cm = new ColumnMeta();
                cm.name = rsmd.getColumnName(i);

                String typeStr = null;
                if (dialect.isKeepByteAndShort()) {
                    int type = rsmd.getColumnType(i);
                    if (type == Types.TINYINT) {
                        typeStr = "java.lang.Byte";
                    } else if (type == Types.SMALLINT) {
                        typeStr = "java.lang.Short";
                    }
                }

                if (typeStr == null) {
                    String colClassName = rsmd.getColumnClassName(i);
                    typeStr = typeMapping.getType(colClassName);
                }

                if (typeStr == null) {
                    int type = rsmd.getColumnType(i);
                    if (type == Types.BINARY || type == Types.VARBINARY || type == Types.LONGVARBINARY || type == Types.BLOB) {
                        typeStr = "byte[]";
                    } else if (type == Types.CLOB || type == Types.NCLOB) {
                        typeStr = "java.lang.String";
                    }
                    // 支持 oracle 的 TIMESTAMP、DATE 字段类型，其中 Types.DATE 值并不会出现
                    // 保留对 Types.DATE 的判断，一是为了逻辑上的正确性、完备性，二是其它类型的数据库可能用得着
                    else if (type == Types.TIMESTAMP || type == Types.DATE) {
                        typeStr = "java.util.Date";
                    }
                    // 支持 PostgreSql 的 jsonb json
                    else if (type == Types.OTHER) {
                        typeStr = "java.lang.Object";
                    } else if (type == Types.INTEGER) {
                        typeStr = "java.lang.Integer";
                    } else {
                        typeStr = "java.lang.String";
                    }
                }
                cm.javaType = typeStr;
                // 构造字段对应的属性名 attrName
                cm.attrName = buildAttrName(cm.name);
                tableMeta.columnMetas.add(cm);
            }
        }
    }
}
